﻿#include "pch.h"
#include "ref/ref.h"

//注册嵌套反射模型
WoRefModelHandle WoRefRegNestingModelEx(const char* typeName, int size) {
    //如果已经注册则返回已注册的信息
    //auto r = WoCodingUTF82GBK(typeName);
    auto regModel = g_RefModeRegister.find(typeName);
    if (regModel != g_RefModeRegister.end()) {
        return regModel->second;
    }
    //如果未注册则进行注册
    auto tmp = new WoRefModelInfo;
    tmp->isNesting = true;
    tmp->refFunc = nullptr;
    tmp->size = size;
    tmp->typeName = typeName;
    g_RefModeRegister[typeName] = tmp;

    return tmp;
};

//注册基础反射模型
WoRefModelHandle WoRefRegBaseModelEx(const char* typeName, int size, WoRefBaseModelFunc refFunc,WoRefBaseModelSezFunc sezFunc) {
    //如果已经注册则返回已注册的信息
    auto regModel = g_RefModeRegister.find(typeName);
    if (regModel != g_RefModeRegister.end()) {
        return regModel->second;
    }
    //如果未注册则进行注册
    auto tmp = new WoRefModelInfo;
    tmp->isNesting = false;
    tmp->refFunc = refFunc;
    tmp->sezFunc = sezFunc;
    tmp->size = size;
    tmp->typeName = typeName;
    g_RefModeRegister[typeName] = tmp;
    return tmp;
}

bool WoRefFillDataEx(void* ptr, const char* typeName, const char* data) {
    auto mr = g_RefModeRegister.find(typeName);
    if (mr == g_RefModeRegister.end()) {
        std::string r = "RefFillBaseData: 类型 ";
        r += typeName;
        r += " 未注册";
        throw std::exception(r.c_str());
        return false;
    }
    auto rFunc = (WoRefBaseModelFunc)mr->second->refFunc;
    if (rFunc != nullptr) {
        rFunc(ptr, data);
    }
    return true;
};

//嵌套类型注册成员
bool WoRefNestingModelRegMemberEx(WoRefModelHandle handle, //注册的句柄
    const char* refName,    //反射的显式名称
    const char* refType,   //反射的类型名称,必须为已注册的类型
    int deviation,          //成员在结构体的偏移地址
    void* retain            //保留参数,非空为getVector地址
) {
    if (handle == nullptr) {
        throw std::exception("RefNestingModelRegMember: 模型句柄不能为NULL");
        return false;
    }
    if (!handle->isNesting) {
        throw std::exception("RefNestingModelRegMember: 句柄指向模型不为结构体模型");
        return false;
    }
    //检查显式反射名是否已注册
    auto memberIterator = handle->memberMap.find(refName);
    if (memberIterator != handle->memberMap.end()) {
        std::string r = "RefNestingModelRegMember: 欲注册成员 ";
        r += refName;
        r += " 已存在";
        throw std::exception(r.c_str());
        return false;
    }
    //检查欲反射的类型是否已注册
    WoRefModelType modelType = WoRefModelType::Bases;
    void* arrayFuncPtr = nullptr;
    auto modelIterator = g_RefModeRegister.find(refType);
    if (modelIterator == g_RefModeRegister.end()) {
        std::string arrName;
        //如果未注册则可能是包裹了容器
        if (!WoRefIfisList(refType, &arrName)) {
			std::string r = "RefNestingModelRegMember: 欲注册成员 ";
			r += refName;
			r += " 的类型是 ";
			r += refType;
			r += " 但是此类型未注册";
			throw std::exception(r.c_str());
			return false;
        }
        //检查嵌套类型是否注册
        auto arrarModelIterator = g_RefModeRegister.find(arrName);
        if (arrarModelIterator == g_RefModeRegister.end()) {
			std::string r = "RefNestingModelRegMember: 欲注册成员 ";
			r += refName;
			r += " 的类型是 ";
			r += refType;
			r += " 但是此类型未注册";
			throw std::exception(r.c_str());
			return false;
        }
        arrayFuncPtr = retain;
        modelType = WoRefModelType::Array;
    }
    auto memberInfo = new WoRefModelMemberInfo;
    memberInfo->typeName = refType;
    memberInfo->deviation = deviation;
    memberInfo->arrayFunc = arrayFuncPtr == nullptr ? RefNestingretainModel{} : *((RefNestingretainModel*)arrayFuncPtr);
    memberInfo->modelType = modelType;
    handle->memberMap[refName] = memberInfo;
    return true;
}

WoRefModelHandle WoRefTypeNameGetHandle(const char*typeName) {
    auto modelIterator = g_RefModeRegister.find(typeName);
    if(modelIterator== g_RefModeRegister.end()){
        return nullptr;
    }
    return modelIterator->second;
}

WoRefBaseModelFunc WoRefTypeNameGetHandleFunc(WoRefModelInfo*info) {
    return info == nullptr ? nullptr : info->refFunc;
}

inline void _ModelToJsonObj(inja::json& json, WoRefModelHandle hModel, void* ptr) {
    CXTextA arrName;
    WoRefArrarType arrType;
    if (!WoRefModelIfisList(hModel->typeName.c_str(), &arrName, &arrType)) {
        //非数组
        for (auto& iter : hModel->memberMap) {
            //json[iter.first]=WoRefModelHandle WEBOAT_API WoRefRegBaseModelEx(const char* typeName, int size, WoRefBaseModelFunc refFunc, WoRefBaseModelSezFunc sezFunc)
            auto sInfo = WoRefTypeNameGetHandle(iter.second->typeName.c_str());
            if (sInfo==nullptr) {
                continue;
            }
            CXTextA str;
            if (sInfo->sezFunc)  {
                sInfo->sezFunc((void*)( (WOPTR)ptr + iter.second->deviation ), str);
            }
            json[iter.first] = str;
        }
        return;
    };
    if (hModel->sizeFunc == nullptr|| hModel->dataFunc == nullptr) {
        return;
    }
    typedef UINT(*WoRefModelRegArraySize)(void*);
    typedef void*(*WoRefModelRegArrayData)(void*);
    auto num = ((WoRefModelRegArraySize)hModel->sizeFunc)(ptr);
    auto data = ((WoRefModelRegArrayData)hModel->dataFunc)(ptr);
    if (data==nullptr)  {
        return;
    }
    auto cmInfo = WoRefTypeNameGetHandle(arrName);
    if (cmInfo==nullptr)  {
        return;
    }
    WOPTR wPtr = (WOPTR)ptr;
    int offset = 0;
    for (int i = 0; i < num; i++) {
        offset= i* cmInfo->size;
        inja::json obj;
        _ModelToJsonObj(obj, cmInfo, (void*)((WOPTR)data+ offset));
        json.push_back(obj);
    }
}

void  WoRefModelToJson(WoTemplateJson&json,const char* modelName, void* modePtr) {
    auto refInfo = WoRefTypeNameGetHandle(modelName);
    if (refInfo == nullptr) {
        throw std::exception("WoResponseSendJsonByModel: 未注册的反射模型");
    }
    _ModelToJsonObj(json, refInfo, modePtr);

}
